/*
 * Copyright 2002-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.context.support;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.*;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.lang.Nullable;

import java.util.*;

/**
 * Delegate for AbstractApplicationContext's post-processor handling.
 * @author Juergen Hoeller
 * @since 4.0
 */
final class PostProcessorRegistrationDelegate {

    private PostProcessorRegistrationDelegate() {
    }

    /**
     * 调用BeanFactoryPostProcessor
     * 主要是分情况处理不同类型的BeanFactoryPostProcessors。
     * BeanFactoryPostProcessors主要分为两类，一类是BeanDefinitionRegistry的BeanFactoryPostProcessor
     * ，另外一类是常规的BeanFactoryPostProcessor。
     * 优先处理前者。同时，这两种后置处理器又被分为从参数里传入和从容器里获取的，最终要将从参数里获取的和从容器里获取的合并在一起。
     * 合并的时候又分为实现了PriorityOrder和普通Order以及没有实现这两个接口的，实现了PriorityOrdered的先执行，
     * 同时是按照PriorityOrdered顺序执行的，其次再到Order，按照Order执行，最后才是没实现这两个接口的，
     * 先执行完BeanDefinitionRegistryPostProcessor的invokeBeanDefinitionRegistryPostProcessors方法，
     * 再对BeanDefinitionRegistryPostProcessor执行invokeBeanFactoryPostProcessors方法，
     * 之后再对常规的BeanFacotryPostProcessors执行invokeBeanFactoryPostProcessors方法
     * @param beanFactory               应用上下文的 BeanFactory 实例
     * @param beanFactoryPostProcessors 应用上下文指定要执行的 BeanFactoryPostProcessor
     **/
    public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory,
                                                       List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        // 如果有BeanDefinitionRegistryPostProcessor的话优先执行
        Set<String> processedBeans = new HashSet<>();
        //如果是BeanDefinitionRegistry类型的话
        if(beanFactory instanceof BeanDefinitionRegistry){
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
            // 用于记录常规 BeanFactoryPostProcessor
            List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
            // 用于记录 BeanDefinitionRegistryPostProcessor
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
            // 遍历所有参数传递进来的 BeanFactoryPostProcessor(它们并没有作为bean注册在容器中)
            // 将所有参数传入的 BeanFactoryPostProcessor 分成两组 :
            // BeanDefinitionRegistryPostProcessor 和常规 BeanFactoryPostProcessor
            // 1.如果是BeanDefinitionRegistryPostProcessor，现在执行postProcessBeanDefinitionRegistry()，
            // 2.否则记录为一个常规 BeanFactoryPostProcessor，暂时不执行处理
            for(BeanFactoryPostProcessor postProcessor: beanFactoryPostProcessors){
                if(postProcessor instanceof BeanDefinitionRegistryPostProcessor){
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor)postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                }else{
                    regularPostProcessors.add(postProcessor);
                }
            }

            // Do not initialize FactoryBeans here: We need to leave all regular beans
            // uninitialized to let the bean factory post-processors apply to them!
            // Separate between BeanDefinitionRegistryPostProcessors that implement
            // PriorityOrdered, Ordered, and the rest.
            //用于记录当前正要被执行的BeanDefinitionRegistryPostProcessor
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

            // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
            // 首先， 对 实现了优先级顺序接口的Bean形式 BeanDefinitionRegistryPostProcessor进行调用
            // 找出所有容器中注册为BeanDefinitionRegistryPostProcessor的postProcessor名字数组
            String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,
                    true, false);
            for(String ppName: postProcessorNames){
                //遍历容器，将BeanDefinitionRegistryPostProcessor类型的后置处理器Bean实例给添加到当前的注册处理器中
                if(beanFactory.isTypeMatch(ppName, PriorityOrdered.class)){
                    currentRegistryProcessors.add(beanFactory.getBean(ppName,
                            BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            //根据优先级排序
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            //按顺序执行BeanDefinitionRegistryPostProcessors
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();

            // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
            //其次对实现了Ordered接口的BeanDefinitionRegistryPostProcessors进行调用
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true,
                    false);
            for(String ppName: postProcessorNames){
                if(!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)){
                    currentRegistryProcessors.add(beanFactory.getBean(ppName,
                            BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            //按照Order排序
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            //将排完序的BeanDefinitionRegistry
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();

            // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
            //最后，执行剩下的BeanDefinitionRegistryPostProcessors
            boolean reiterate = true;
            while(reiterate){
                reiterate = false;
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true,
                        false);
                for(String ppName: postProcessorNames){
                    if(!processedBeans.contains(ppName)){
                        currentRegistryProcessors.add(beanFactory.getBean(ppName,
                                BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                        reiterate = true;
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                currentRegistryProcessors.clear();
            }

            // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
            // 因为BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor,所以这里
            // 也对所有 BeanDefinitionRegistryPostProcessor 调用其方法 postProcessBeanFactory()
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            // 对所有常规 BeanFactoryPostProcessor 调用其方法 postProcessBeanFactory()
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }else{
            // Invoke factory processors registered with the context instance.
            //如果都是常规的BeanFactoryPostProcessor，则调用其方法 postProcessBeanFactory()
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }
        // 上面逻辑执行了以参数形式传入的BeanDefinitionRegistryPostProcessor以及常规的BeanFactoryPostProcessor
        // 也执行了容器里面的BeanDefinitionRegistryPostProcessor，故还剩下容器里面的BeanFactoryPostProcessor需要去处理
        // 逻辑是一样的，也分为实现了PriorityOrdered和Ordered以及两个都没实现的
        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

        // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for(String ppName: postProcessorNames){
            if(processedBeans.contains(ppName)){
                // skip - already processed in first phase above
            }else if(beanFactory.isTypeMatch(ppName, PriorityOrdered.class)){
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            }else if(beanFactory.isTypeMatch(ppName, Ordered.class)){
                orderedPostProcessorNames.add(ppName);
            }else{
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
        for(String postProcessorName: orderedPostProcessorNames){
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

        // Finally, invoke all other BeanFactoryPostProcessors.
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
        for(String postProcessorName: nonOrderedPostProcessorNames){
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

        // Clear cached merged bean definitions since the post-processors might have
        // modified the original metadata, e.g. replacing placeholders in values...
        beanFactory.clearMetadataCache();
    }

    public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory,
                                                  AbstractApplicationContext applicationContext) {
        // 所有的 BeanPostProcessors
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

        // Register BeanPostProcessorChecker that logs an info message when
        // a bean is created during BeanPostProcessor instantiation, i.e. when
        // a bean is not eligible for getting processed by all BeanPostProcessors.
        // 注册 BeanPostProcessorChecker
        // 主要用于记录一些 bean 的信息，这些 bean 不符合所有 BeanPostProcessors 处理的资格时
        int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
        beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

        // Separate between BeanPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        // 区分 PriorityOrdered、Ordered 、以及非两者
        List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for(String ppName: postProcessorNames){
            if(beanFactory.isTypeMatch(ppName, PriorityOrdered.class)){
                BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
                priorityOrderedPostProcessors.add(pp);
                if(pp instanceof MergedBeanDefinitionPostProcessor){
                    internalPostProcessors.add(pp);
                }
            }else if(beanFactory.isTypeMatch(ppName, Ordered.class)){
                orderedPostProcessorNames.add(ppName);
            }else{
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // First, register the BeanPostProcessors that implement PriorityOrdered.
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

        // Next, register the BeanPostProcessors that implement Ordered.
        List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
        for(String ppName: orderedPostProcessorNames){
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            orderedPostProcessors.add(pp);
            if(pp instanceof MergedBeanDefinitionPostProcessor){
                internalPostProcessors.add(pp);
            }
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, orderedPostProcessors);

        // Now, register all regular BeanPostProcessors.
        List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
        for(String ppName: nonOrderedPostProcessorNames){
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            nonOrderedPostProcessors.add(pp);
            if(pp instanceof MergedBeanDefinitionPostProcessor){
                internalPostProcessors.add(pp);
            }
        }
        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

        // Finally, re-register all internal BeanPostProcessors.
        sortPostProcessors(internalPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, internalPostProcessors);

        // Re-register post-processor for detecting inner beans as ApplicationListeners,
        // moving it to the end of the processor chain (for picking up proxies etc).
        // 重新注册用来自动探测内部ApplicationListener的postprocessor，
        // 这样可以将他们移到处理器链条的末尾
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    }

    private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {
        Comparator<Object> comparatorToUse = null;
        if(beanFactory instanceof DefaultListableBeanFactory){
            //可选的用于依赖数组集合的比较器
            comparatorToUse = ((DefaultListableBeanFactory)beanFactory).getDependencyComparator();
        }
        if(comparatorToUse == null){
            //如果没有，则看看执行的顺序
            comparatorToUse = OrderComparator.INSTANCE;
        }
        //根据comparatorToUse进行比较
        postProcessors.sort(comparatorToUse);
    }

    /**
     * Invoke the given BeanDefinitionRegistryPostProcessor beans.
     */
    private static void invokeBeanDefinitionRegistryPostProcessors(Collection<?
            extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

        for(BeanDefinitionRegistryPostProcessor postProcessor: postProcessors){
            postProcessor.postProcessBeanDefinitionRegistry(registry);
        }
    }

    /**
     * Invoke the given BeanFactoryPostProcessor beans.
     */
    private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors
            , ConfigurableListableBeanFactory beanFactory) {

        for(BeanFactoryPostProcessor postProcessor: postProcessors){
            postProcessor.postProcessBeanFactory(beanFactory);
        }
    }

    /**
     * Register the given BeanPostProcessor beans.
     */
    private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory,
                                                   List<BeanPostProcessor> postProcessors) {

        for(BeanPostProcessor postProcessor: postProcessors){
            beanFactory.addBeanPostProcessor(postProcessor);
        }
    }

    /**
     * BeanPostProcessor that logs an info message when a bean is created during
     * BeanPostProcessor instantiation, i.e. when a bean is not eligible for
     * getting processed by all BeanPostProcessors.
     */
    private static final class BeanPostProcessorChecker implements BeanPostProcessor {

        private static final Log logger = LogFactory.getLog(BeanPostProcessorChecker.class);

        private final ConfigurableListableBeanFactory beanFactory;

        private final int beanPostProcessorTargetCount;

        public BeanPostProcessorChecker(ConfigurableListableBeanFactory beanFactory, int beanPostProcessorTargetCount) {
            this.beanFactory = beanFactory;
            this.beanPostProcessorTargetCount = beanPostProcessorTargetCount;
        }

        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) {
            return bean;
        }

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) {
            if(!(bean instanceof BeanPostProcessor)
                    && !isInfrastructureBean(beanName)
                    && this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount){
                if(logger.isInfoEnabled()){
                    logger.info("Bean '"
                            + beanName
                            + "' of type ["
                            + bean.getClass().getName()
                            + "] is not eligible for getting processed by all BeanPostProcessors "
                            + "(for example: not eligible for auto-proxying)");
                }
            }
            return bean;
        }

        private boolean isInfrastructureBean(@Nullable String beanName) {
            if(beanName != null && this.beanFactory.containsBeanDefinition(beanName)){
                BeanDefinition bd = this.beanFactory.getBeanDefinition(beanName);
                return (bd.getRole() == RootBeanDefinition.ROLE_INFRASTRUCTURE);
            }
            return false;
        }

    }

}
